package br.ufmg.dcc.vod.remoteworkers.async;

import java.rmi.RemoteException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import br.ufmg.dcc.vod.remoteworkers.AbstractTestCase;
import br.ufmg.dcc.vod.remoteworkers.CommandError;
import br.ufmg.dcc.vod.remoteworkers.util.SemaphorePostRaceWaitCommand;

public class AbstractQueueBasedCommandInterestedTest extends AbstractTestCase {

	public void testStartAndStop() throws RemoteException, InterruptedException {
		MyCommandInterested processor = new MyCommandInterested(PORT);
		processor.start();
		
		try {
		 processor.start();
		 fail();
		} catch (Exception e) { }
		
		processor.stop(false, Long.MAX_VALUE, TimeUnit.DAYS);
		
		try {
			 processor.start();
			 fail();
		} catch (Exception e) { }
		
		try {
			processor.stop(false, Long.MAX_VALUE, TimeUnit.DAYS);
			fail();
		} catch (Exception e) { }
	}
	
	public void testProcess() throws RemoteException, InterruptedException {
		
		QueueBasedAsyncRemoteProcessor processor = new QueueBasedAsyncRemoteProcessor(PORT);
		processor.start();
		MyCommandInterested interested = new MyCommandInterested(PORT);
		interested.start();
		
		Semaphore semaphore = new Semaphore(0);
		for (int i = 0; i <= 10; i++) {
			processor.process(new SimpleCommandRequest<Integer, Integer>(new SemaphorePostRaceWaitCommand(semaphore), interested, ""));
		}
		
		semaphore.acquire(11); //everybody has been processed
		processor.stop(true, Long.MAX_VALUE, TimeUnit.DAYS); //stopping processor and waiting for last command to finish
		interested.stop(true, Long.MAX_VALUE, TimeUnit.DAYS); //stopping interested
		
		assertEquals(10, interested.expectedID);
	}
	
	private class MyCommandInterested extends AbstractQueueBasedCommandInterested<Integer, Integer> {

		private int expectedID = -1;
		
		public MyCommandInterested(int port) throws RemoteException {
			super(port);
		}

		@Override
		public void realCommandError(Integer i, CommandError e) {
			assertFalse(true);
		}

		@Override
		public void realCommandResponse(Integer i, Integer t) {
			assertEquals(i.intValue(), t.intValue());
			assertEquals(++expectedID, i.intValue());
		}
		
	}
}